package com.twu.biblioteca;

import java.io.InputStream;
import java.util.Scanner;

public enum State {

    WELCOME_MESSAGE {
        @Override
        public String printStateOutput() {
            return "\nHallo User, welcome to the Biblioteca!\n";
        }

        @Override
        public State processInput(InputStream inputStream) {
            return MAIN_MENU;
        }
    },

    MAIN_MENU {
        @Override
        public String printStateOutput() {
            StringBuilder builder = new StringBuilder();
            builder.append("\nMain Menu:\n");
            builder.append("LIST_BOOKS ==> List Books.\n");
            builder.append("RETURN_BOOK ==> Return Book.\n");
            builder.append("LIST_MOVIES ==> List Movies.\n");
            if (Userstore.getInstance().getCurrentUser() != null) {
                builder.append("USER_INFO ==> Show user information.\n");
            }
            builder.append("QUIT ==> Quit.\n");
            builder.append("\n");
            builder.append("Type in your command:");
            return builder.toString();
        }

        @Override
        public State processInput(InputStream inputStream) {
            Scanner scanner = new Scanner(inputStream);
            String input = scanner.nextLine();

            try {
                if (Userstore.getInstance().getCurrentUser() == null && input.equals(USER_INFO.toString())) {
                    return INVALID_MENU_OPTION;
                }
                return State.valueOf(input);
            } catch (Exception e) {
                return INVALID_MENU_OPTION;
            }
        }
    },

    USER_INFO {

        @Override
        public String printStateOutput() {
            StringBuilder builder = new StringBuilder();
            builder.append("\nUser information:\n");
            builder.append(Userstore.getInstance().getCurrentUser().toString());
            return builder.toString();
        }

        @Override
        public State processInput(InputStream inputStream) {
            return MAIN_MENU;
        }
    },

    INVALID_MENU_OPTION {
        @Override
        public String printStateOutput() {
            return "\nSelect a valid option!\n";
        }

        @Override
        public State processInput(InputStream inputStream) {
            return MAIN_MENU;
        }
    },

    LIST_MOVIES {

        @Override
        public String printStateOutput() {
            StringBuilder builder = new StringBuilder();

            builder.append("\nMovies:\n");
            for (Movie movie : Moviestore.getInstance().getAvailableMovies()) {
                builder.append(String.format("%s\n", movie));
            }
            builder.append("\n");
            builder.append("CHECKOUT_MOVIE ==> Checkout a movie.\n");
            builder.append("everything else ==> Back to Main Menu.\n");
            builder.append("Choose Command:");

            return builder.toString();
        }

        @Override
        public State processInput(InputStream inputStream) {
            Scanner scanner = new Scanner(inputStream);
            String input = scanner.nextLine();

            try {
                return State.valueOf(input);
            } catch (Exception e) {
                return MAIN_MENU;
            }
        }
    },

    CHECKOUT_MOVIE {
        @Override
        public String printStateOutput() {
            StringBuilder builder = new StringBuilder();

            builder.append("\nSelect movie:\n");
            int i = 0;
            for (Movie movie : Moviestore.getInstance().getAvailableMovies()) {
                builder.append(String.format("%2d | %s\n",
                        i++, movie.getName()));
            }
            builder.append("\n");
            builder.append("Type in number for movie to checkout:");

            return builder.toString();
        }

        @Override
        public State processInput(InputStream inputStream) {
            Scanner scanner = new Scanner(inputStream);
            String input = scanner.nextLine();

            try {
                Movie movie = Moviestore.getInstance().getAvailableMovies().get(Integer.parseInt(input));
                if (Moviestore.getInstance().checkoutMovie(movie)) {
                    System.out.println("Successfully checked out movie!");
                    return MAIN_MENU;
                } else {
                    System.out.println("Unsuccessfully checked out movie!");
                    return MAIN_MENU;
                }
            } catch (Exception e) {
                System.out.println("Invalid input!");
                return MAIN_MENU;
            }
        }
    },

    LIST_BOOKS {
        @Override
        public String printStateOutput() {
            StringBuilder builder = new StringBuilder();

            builder.append("\nBooks:\n");
            for (Book book : Bookstore.getInstance().getAvailableBooks()) {
                builder.append(String.format("%s\n", book.getTitle()));
            }
            builder.append("\n");
            builder.append("BOOK_DETAILS ==> Show details of a book.\n");
            builder.append("CHECKOUT_BOOK ==> Checkout a book.\n");
            builder.append("everything else ==> Back to Main Menu.\n");
            builder.append("Choose Command:");

            return builder.toString();
        }

        @Override
        public State processInput(InputStream inputStream) {
            Scanner scanner = new Scanner(inputStream);
            String input = scanner.nextLine();

            try {
                return State.valueOf(input);
            } catch (Exception e) {
                return MAIN_MENU;
            }
        }
    },

    BOOK_DETAILS {
        @Override
        public String printStateOutput() {
            StringBuilder builder = new StringBuilder();

            builder.append("\nSelect book:\n");
            int i = 0;
            for (Book book : Bookstore.getInstance().getAvailableBooks()) {
                builder.append(String.format("%2d | %s\n",
                        i++, book.getTitle()));
            }
            builder.append("\n");
            builder.append("Type in number for book to show details:");

            return builder.toString();
        }

        @Override
        public State processInput(InputStream inputStream) {
            Scanner scanner = new Scanner(inputStream);
            String input = scanner.nextLine();

            try {
                Book book = Bookstore.getInstance().getAvailableBooks().get(Integer.parseInt(input));
                System.out.printf("\n%15s | %15s | %4s\n", book.getTitle(), book.getAuthor(), book.getPublished());
                return MAIN_MENU;
            } catch (Exception e) {
                System.out.println("Invalid input!");
                return MAIN_MENU;
            }
        }
    },

    CHECKOUT_BOOK {
        @Override
        public String printStateOutput() {
            StringBuilder builder = new StringBuilder();

            builder.append("\nSelect book:\n");
            int i = 0;
            for (Book book : Bookstore.getInstance().getAvailableBooks()) {
                builder.append(String.format("%2d | %s\n",
                        i++, book.getTitle()));
            }

            return builder.toString();
        }

        @Override
        public State processInput(InputStream inputStream) {
            while (Userstore.getInstance().getCurrentUser() == null) {
                System.out.println("You have to login first!");
                System.out.println("Login number:");
                Scanner scanner = new Scanner(inputStream);
                String number = scanner.nextLine();

                System.out.println("password:");
                String password = scanner.nextLine();

                Userstore.getInstance().login(number, password);
            }

            System.out.println("\nType in number for book to checkout:");
            Scanner scanner = new Scanner(inputStream);
            String input = scanner.nextLine();

            try {
                Book book = Bookstore.getInstance().getAvailableBooks().get(Integer.parseInt(input));
                if (Bookstore.getInstance().checkoutBook(book)) {
                    return SUCCESSFUL_CHECKOUT;
                } else {
                    return UNSUCCESSFUL_CHECKOUT;
                }
            } catch (Exception e) {
                System.out.println("Invalid input!");
                return MAIN_MENU;
            }
        }
    },

    SUCCESSFUL_CHECKOUT {
        @Override
        public String printStateOutput() {
            return "\nCheckout book was successful!";
        }

        @Override
        public State processInput(InputStream inputStream) {
            return MAIN_MENU;
        }
    },

    UNSUCCESSFUL_CHECKOUT {
        @Override
        public String printStateOutput() {
            return "\nCheckout book was NOT successful!";
        }

        @Override
        public State processInput(InputStream inputStream) {
            return MAIN_MENU;
        }
    },

    QUIT {
        @Override
        public String printStateOutput() {
            return "Bye bye!";
        }

        @Override
        public State processInput(InputStream inputStream) {
            // nothing to do!
            return null;
        }
    },

    RETURN_BOOK {
        @Override
        public String printStateOutput() {
            StringBuilder builder = new StringBuilder();

            builder.append("\nSelect book:\n");
            int i = 0;
            for (Book book : Bookstore.getInstance().getRentBooks()) {
                builder.append(String.format("%2d | %s\n",
                        i++, book.getTitle()));
            }
            builder.append("\n");
            builder.append("Type in number for book to return:");

            return builder.toString();
        }

        @Override
        public State processInput(InputStream inputStream) {
            Scanner scanner = new Scanner(inputStream);
            String input = scanner.nextLine();

            try {
                Book book = Bookstore.getInstance().getRentBooks().get(Integer.parseInt(input));
                if (Bookstore.getInstance().returnBook(book)) {
                    return SUCCESSFUL_RETURN;
                } else {
                    return UNSUCCESSFUL_RETURN;
                }
            } catch (Exception e) {
                System.out.println("Invalid input!");
                return MAIN_MENU;
            }
        }
    },

    SUCCESSFUL_RETURN {
        @Override
        public String printStateOutput() {
            return "\nSuccessfully returned book!";
        }

        @Override
        public State processInput(InputStream inputStream) {
            return MAIN_MENU;
        }
    },

    UNSUCCESSFUL_RETURN {
        @Override
        public String printStateOutput() {
            return "\nReturning book failed!";
        }

        @Override
        public State processInput(InputStream inputStream) {
            return MAIN_MENU;
        }
    };

    public abstract String printStateOutput();

    public abstract State processInput(InputStream inputStream);



}
